package commands

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/spf13/cobra"
)

var (
    providerCmd = &cobra.Command{
        Use:   "provider",
        Short: "Provider helpers and scaffolding",
    }

    providerInitCmd = &cobra.Command{
        Use:   "init [dir]",
        Short: "Scaffold a Terraform workspace for the OpenTaco provider",
        Args:  cobra.MaximumNArgs(1),
        RunE:  runProviderInit,
    }

    initDir      string
    initSystemID string
    initForce    bool
    initNoCreate bool
)

func init() {
    // Attach provider command group
    rootCmd.AddCommand(providerCmd)

    // Add init subcommand
    providerCmd.AddCommand(providerInitCmd)

    // Flags
    providerInitCmd.Flags().StringVar(&initDir, "dir", "opentaco-config", "Directory to write Terraform files")
    providerInitCmd.Flags().StringVar(&initSystemID, "system-unit", "__opentaco_system", "System unit ID for provider backend")
    providerInitCmd.Flags().BoolVar(&initForce, "force", false, "Overwrite files if they already exist")
    providerInitCmd.Flags().BoolVar(&initNoCreate, "no-create", false, "Do not create the system unit; only scaffold files")
}

func runProviderInit(cmd *cobra.Command, args []string) error {
    // If a positional dir is provided, it takes precedence over --dir
    if len(args) > 0 {
        initDir = args[0]
    }
    // Normalize server URL (from global flag)
    base := strings.TrimRight(serverURL, "/")

    // Optionally create the system unit via API (idempotent-ish)
    if !initNoCreate {
        client := newAuthedClient()

        // Check existence first
        _, err := client.GetUnit(context.Background(), initSystemID)
        if err != nil {
            if !isHTTPError(err, 404) {
                // Unknown error; continue but warn
                fmt.Fprintf(os.Stderr, "[WARN] Could not check system unit: %v\n", err)
            }
            // Try to create
            if _, cErr := client.CreateUnit(context.Background(), initSystemID); cErr != nil {
                if !isHTTPError(cErr, 409) { // already exists is ok
                    return fmt.Errorf("failed to create system unit %q: %w", initSystemID, cErr)
                }
            } else {
                fmt.Fprintf(os.Stdout, "Created system unit: %s\n", initSystemID)
            }
        }
    }

    // Ensure directory
    if err := os.MkdirAll(initDir, 0o755); err != nil {
        return fmt.Errorf("failed to create directory %s: %w", initDir, err)
    }

    // Write .gitignore
    giPath := filepath.Join(initDir, ".gitignore")
    if err := writeFileUnlessExists(giPath, terraformGitignore(), initForce); err != nil {
        return err
    }

    // Write main.tf
    tfPath := filepath.Join(initDir, "main.tf")
    content := terraformMainTF(base, initSystemID)
    if err := writeFileUnlessExists(tfPath, content, initForce); err != nil {
        return err
    }

    fmt.Fprintf(os.Stdout, "Scaffolded Terraform workspace in %s\n", initDir)
    fmt.Fprintf(os.Stdout, "Run: cd %s && terraform init && terraform apply\n", initDir)
    return nil
}

func writeFileUnlessExists(path, content string, force bool) error {
    if !force {
        if _, err := os.Stat(path); err == nil {
            fmt.Fprintf(os.Stdout, "Skipped existing file: %s (use --force to overwrite)\n", path)
            return nil
        }
    }
    return os.WriteFile(path, []byte(content), 0o644)
}

func terraformMainTF(baseURL, systemID string) string {
    now := time.Now().Format(time.RFC3339)
    return fmt.Sprintf(`# Generated by taco provider init on %s

terraform {
  backend "http" {
    address        = "%s/v1/backend/%s"
    lock_address   = "%s/v1/backend/%s"
    unlock_address = "%s/v1/backend/%s"
  }

  required_providers {
    opentaco = {
      source = "digger/opentaco"
    }
  }
}

provider "opentaco" {
  endpoint = "%s"
}

# Demo resource: registers a user unit managed by OpenTaco
resource "opentaco_unit" "example" {
  id = "myapp/prod"
}
`,
        now,
        baseURL, systemID,
        baseURL, systemID,
        baseURL, systemID,
        baseURL,
    )
}

func terraformGitignore() string {
    return ".terraform/\n.terraform.lock.hcl\nterraform.tfstate\nterraform.tfstate.backup\n"
}

func isHTTPError(err error, code int) bool {
    if err == nil {
        return false
    }
    prefix := fmt.Sprintf("HTTP %d:", code)
    return strings.HasPrefix(err.Error(), prefix)
}
